home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 007 (1987-02-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 007 (1987-02-15)(Ossowski, Stefan)(DE)(PD).adf / C Compiler / register.c < prev    next >
C/C++ Source or Header  |  1987-03-04  |  5KB  |  163 lines

  1. #include        <stdio.h>
  2. #include        "c.h"
  3. #include        "expr.h"
  4. #include        "gen.h"
  5. #include        "cglbdec.h"
  6.  
  7. /*
  8.  *    68000 C compiler
  9.  *
  10.  *    Copyright 1984, 1985, 1986 Matthew Brandt.
  11.  *    all commercial rights reserved.
  12.  *
  13.  *    This compiler is intended as an instructive tool for personal use. Any
  14.  *    use for profit without the written consent of the author is prohibited.
  15.  *
  16.  *    This compiler may be distributed freely for non-commercial use as long
  17.  *    as this notice stays intact. Please forward any enhancements or questions
  18.  *    to:
  19.  *
  20.  *        Matthew Brandt
  21.  *        Box 920337
  22.  *        Norcross, Ga 30092
  23.  */
  24.  
  25. /*
  26.  *      this module handles the allocation and de-allocation of
  27.  *      temporary registers. when a temporary register is allocated
  28.  *      the stack depth is saved in the field deep of the address
  29.  *      mode structure. when validate is called on an address mode
  30.  *      structure the stack is popped until the register is restored
  31.  *      to it's pre-push value.
  32.  */
  33.  
  34. struct amode    push[] = { {am_adec,7} },
  35.                 pop[] = { {am_ainc,7} };
  36. int             next_data,
  37.                 next_addr;
  38. int             max_data,
  39.                 max_addr;
  40.  
  41. gen_push(reg,rmode)
  42. /*
  43.  *      this routine generates code to push a register onto the stack
  44.  */
  45. int     reg;
  46. enum e_am rmode;
  47. {       struct amode    *ap1;
  48.         ap1 = xalloc(sizeof(struct amode));
  49.         ap1->preg = reg;
  50.         ap1->mode = rmode;
  51.         gen_code(op_move,4,ap1,push);
  52. }
  53.  
  54. gen_pop(reg,rmode)
  55. /*
  56.  *      generate code to pop the primary register in ap from the
  57.  *      stack.
  58.  */
  59. int     reg;
  60. enum e_am rmode;
  61. {       struct amode    *ap1;
  62.         ap1 = xalloc(sizeof(struct amode));
  63.         ap1->preg = reg;
  64.         ap1->mode = rmode;
  65.         gen_code(op_move,4,pop,ap1);
  66. }
  67.  
  68. initstack()
  69. /*
  70.  *      this routine should be called before each expression is
  71.  *      evaluated to make sure the stack is balanced and all of
  72.  *      the registers are marked free.
  73.  */
  74. {       next_data = 0;
  75.         next_addr = 0;
  76.         max_data = 2;
  77.         max_addr = 1;
  78. }
  79.  
  80. validate(ap)
  81. /*
  82.  *      validate will make sure that if a register within an address
  83.  *      mode has been pushed onto the stack that it is popped back
  84.  *      at this time.
  85.  */
  86. struct amode    *ap;
  87. {       switch( ap->mode )
  88.                 {
  89.                 case am_direct:
  90.                 case am_immed:
  91.                         return;         /* no registers used */
  92.                 case am_dreg:
  93.                         if( ap->preg > 2 )
  94.                                 return; /* not a temporary */
  95.                         if( max_data - ap->deep >= 3 )
  96.                                 {
  97.                                 gen_pop(ap->preg,am_dreg);
  98.                                 --max_data;
  99.                                 }
  100.                         break;
  101.                 default:
  102.                         if( ap->preg > 1 )
  103.                                 return; /* not a temp register */
  104.                         if( max_addr - ap->deep >= 2 )
  105.                                 {
  106.                                 gen_pop(ap->preg,am_areg);
  107.                                 --max_addr;
  108.                                 }
  109.                         break;
  110.                 }
  111. }
  112.  
  113. struct amode    *temp_data()
  114. /*
  115.  *      allocate a temporary data register and return it's
  116.  *      addressing mode.
  117.  */
  118. {       struct amode    *ap;
  119.         ap = xalloc(sizeof(struct amode));
  120.         ap->mode = am_dreg;
  121.         ap->preg = next_data % 3;
  122.         ap->deep = next_data;
  123.         if( next_data > max_data )
  124.                 {
  125.                 gen_push(next_data % 3,am_dreg);
  126.                 max_data = next_data;
  127.                 }
  128.         ++next_data;
  129.         return ap;
  130. }
  131.  
  132. struct amode    *temp_addr()
  133. /*
  134.  *      allocate a temporary address register and return it's
  135.  *      addressing mode.
  136.  */
  137. {       struct amode    *ap;
  138.         ap = xalloc(sizeof(struct amode));
  139.         ap->mode = am_areg;
  140.         ap->preg = next_addr % 2;
  141.         ap->deep = next_addr;
  142.         if( next_addr > max_addr )
  143.                 {
  144.                 gen_push(next_addr % 2,am_areg);
  145.                 max_addr = next_addr;
  146.                 }
  147.         ++next_addr;
  148.         return ap;
  149. }
  150.  
  151. freeop(ap)
  152. /*
  153.  *      release any temporary registers used in an addressing mode.
  154.  */
  155. struct amode    *ap;
  156. {       if( ap->mode == am_immed || ap->mode == am_direct )
  157.                 return;         /* no registers used */
  158.         if( ap->mode == am_dreg && ap->preg < 3 )
  159.                 --next_data;
  160.         else if( ap->preg < 2 )
  161.                 --next_addr;
  162. }
  163.